package com.github.aloxc.plugin.restplus.component;

import com.github.aloxc.plugin.restplus.common.Consts;
import com.github.aloxc.plugin.restplus.entity.*;
import com.github.aloxc.plugin.restplus.i18n.I18Bundle;
import com.github.aloxc.plugin.restplus.listener.*;
import com.github.aloxc.plugin.restplus.navigator.RestServicesNavigator;
import com.intellij.openapi.editor.colors.FontPreferences;
import com.intellij.openapi.project.Project;
import com.intellij.ui.components.JBPanel;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.core.GridLayoutManager;

import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumnModel;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import static com.github.aloxc.plugin.restplus.common.Consts.LINE_NUMBER_BACKGROUND_COLOR;
import static javax.swing.ScrollPaneConstants.*;

/**
 * 变量ui
 *
 * @author leero
 */
public class Variate extends JBPanel implements ISettingPanel {
    private JPanel rootPanel;
    private JPanel variatePanel;
    private JButton variateSaveButton;
    private JButton variateCancelButton;
    private JTable variateTable;
    private JPanel tablePanel;
    private JPanel buttonPanel;
    private JScrollPane tableScrollPanel;
    private JButton variateDeleteButton;
    private JButton variateAddButton;
    private JButton deleteEnvironmentButton;
    private JScrollPane textScrollPanel;
    private JLabel testLabel;
    private JPanel topPanel;
    private Dialog dialog;
    private JCheckBox httpsCheckBox;
    private JTextField hostTextField;
    private JTextField portTextField;
    private JTextField contextTextField;
    private Project project;
    private JTextField nameTextField;
    private SettingType settingType;
    private JLabel nameLabel;
    private JLabel contextLabel;
    private JLabel httpsLabel;
    private JLabel hostLabel;
    private JLabel portLabel;
    private JLabel tipsLabel;

    private String url;
    private String parentName;
    private TextPane testTextArea;

    public TextPane getTestTextArea() {
        return testTextArea;
    }

    public JPanel getRootPanel() {
        return rootPanel;
    }

    public String getUrl() {
        return url;
    }

    public JCheckBox getHttpsCheckBox() {
        return httpsCheckBox;
    }

    public JTextField getHostTextField() {
        return hostTextField;
    }

    public JTextField getPortTextField() {
        return portTextField;
    }

    public JTextField getContextTextField() {
        return contextTextField;
    }

    public String getParentName() {
        return parentName;
    }

    public void setSettingType(SettingType settingType) {
        this.settingType = settingType;
    }

    public JTable getVariateTable() {
        return variateTable;
    }

    public JScrollPane getTableScrollPanel() {
        return tableScrollPanel;
    }

    @Override
    protected void printComponent(Graphics g) {
        super.printComponent(g);
    }

    public Variate() {
        super();
        initComponent();
    }

    public Variate(SettingType settingType, String url, Project project, String parentName,Dialog dialog) {
        super();
        this.url = url;
        this.parentName = parentName;
        this.setSettingType(settingType);
        this.project = project;
        this.dialog = dialog;
        initComponent();
    }

    public Variate(SettingType settingType, Project project, Dialog dialog, SettingListenerContext context) {
        super();
        this.settingType = settingType;
        this.project = project;
        this.dialog = dialog;
        initComponent();
    }

    private void initComponent() {
        initUi();
        initAction();
    }


    private void initUi() {
        GridLayoutManager variateLayoutManager = new GridLayoutManager(5, 1);
        variateLayoutManager.setHGap(1);
        variateLayoutManager.setVGap(1);
        variateLayoutManager.setMargin(new Insets(0, 0, 0, 0));
        variatePanel = new JBPanel<>();
        variatePanel.setLayout(variateLayoutManager);
        this.setBorder(BorderFactory.createEmptyBorder());
        this.setLayout(new GridLayoutManager(1, 1));

        Font font = getEffectiveFont();
        testTextArea = new TextPane(LINE_NUMBER_BACKGROUND_COLOR, project);
        testTextArea.setToolTipText(I18Bundle.getMessage("com.github.aloxc.plugin.restplus.textpane.testtooltips.text"));
        TextPaneKeyAdapter textPaneKeyAdapter = new TextPaneKeyAdapter(testTextArea, true);
        testTextArea.setJavascript(true);
        testTextArea.addKeyListener(textPaneKeyAdapter);
        testTextArea.addMouseListener(textPaneKeyAdapter);
        testTextArea.setShowLineNumber(true);
        testTextArea.setFont(font);

        initText();
        initTopPanel();
        initTable();
        initTestText();
        initTest();
        initButton();

        Dimension variatePanelSize = new Dimension(815, 600);

        this.add(variatePanel,
                new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_NORTHWEST, GridConstraints.FILL_BOTH,
                        GridConstraints.FILL_BOTH,
                        GridConstraints.FILL_BOTH,
                        variatePanelSize, variatePanelSize, variatePanelSize));


        deleteEnvironmentButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        variateDeleteButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        variateCancelButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        variateAddButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        variateSaveButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));

    }

    private final FontPreferences getFontPreferences() {
        return new FontPreferences();
    }

    private Font getEffectiveFont() {
        FontPreferences fontPreferences = this.getFontPreferences();
        String fontFamily = fontPreferences.getFontFamily();
        int size = fontPreferences.getSize(fontFamily);
        return new Font("Monospaced", Font.PLAIN, size);
    }


    private Font getEffectiveFont(String text) {
        FontPreferences fontPreferences = this.getFontPreferences();
        List<String> effectiveFontFamilies = fontPreferences.getEffectiveFontFamilies();
        int size = fontPreferences.getSize(fontPreferences.getFontFamily());
        Font font = new Font(FontPreferences.DEFAULT_FONT_NAME, Font.PLAIN, size);
        for (String effectiveFontFamily : effectiveFontFamilies) {
            Font effectiveFont = new Font(effectiveFontFamily, Font.PLAIN, size);
            if (effectiveFont.canDisplayUpTo(text) == -1) {
                font = effectiveFont;
                break;
            }
        }
        return font;
    }

    private void initText() {
        this.deleteEnvironmentButton.setText(I18Bundle.getMessage("com.github.aloxc.plugin.restplus.setting.environment.delete"));
        this.variateDeleteButton.setText(I18Bundle.getMessage("com.github.aloxc.plugin.restplus.setting.delete.button"));
        this.variateCancelButton.setText(I18Bundle.getMessage("com.github.aloxc.plugin.restplus.setting.cancel"));
        this.variateSaveButton.setText(I18Bundle.getMessage("com.github.aloxc.plugin.restplus.setting.save"));
        this.variateAddButton.setText(I18Bundle.getMessage("com.github.aloxc.plugin.restplus.setting.add"));
        this.testLabel.setText(I18Bundle.getMessage("com.github.aloxc.plugin.restplus.setting.tests"));
        this.tipsLabel.setText(I18Bundle.getMessage("com.github.aloxc.plugin.restplus.setting.tips"));

        this.nameLabel.setText(I18Bundle.getMessage("com.github.aloxc.plugin.restplus.setting.environment.name"));
        this.contextLabel.setText(I18Bundle.getMessage("com.github.aloxc.plugin.restplus.setting.environment.context"));
        this.hostLabel.setText(I18Bundle.getMessage("com.github.aloxc.plugin.restplus.setting.environment.host"));
        this.portLabel.setText(I18Bundle.getMessage("com.github.aloxc.plugin.restplus.setting.environment.port"));
        this.httpsLabel.setText(I18Bundle.getMessage("com.github.aloxc.plugin.restplus.setting.environment.https"));

    }

    /**
     * 设置顶部一些设置框和提示的显示与否
     *
     * @param isEnvironmentSetting
     */
    public void setTopInfo(boolean isEnvironmentSetting) {
        this.nameLabel.setVisible(isEnvironmentSetting);
        this.nameTextField.setVisible(isEnvironmentSetting);
        this.contextLabel.setVisible(isEnvironmentSetting);
        this.contextTextField.setVisible(isEnvironmentSetting);
        this.httpsLabel.setVisible(isEnvironmentSetting);
        this.httpsCheckBox.setVisible(isEnvironmentSetting);
        this.hostLabel.setVisible(isEnvironmentSetting);
        this.hostTextField.setVisible(isEnvironmentSetting);
        this.portLabel.setVisible(isEnvironmentSetting);
        this.portTextField.setVisible(isEnvironmentSetting);
        this.tipsLabel.setVisible(!isEnvironmentSetting);
    }

    private void initTopPanel() {
        int topHeight = 26;//32
        boolean https = false;
        String host = null;
        int port = 80;
        RestConfig config = project.getComponent(RestServicesNavigator.class).getConfig();

        Dimension topSize = new Dimension(-1, topHeight);
        topPanel = new JBPanel<>();
        topPanel.setMaximumSize(topSize);
        topPanel.setMinimumSize(topSize);
        topPanel.setPreferredSize(topSize);
        FlowLayout topPanelLayout = new FlowLayout();
        topPanelLayout.setHgap(1);
        topPanelLayout.setVgap(1);
        topPanelLayout.setAlignment(FlowLayout.LEFT);
        hostTextField.setPreferredSize(new Dimension(120, topHeight));
        nameTextField.setPreferredSize(new Dimension(120, topHeight));
        contextTextField.setPreferredSize(new Dimension(150, topHeight));
        portTextField.setPreferredSize(new Dimension(90, topHeight));
        topPanel.setLayout(topPanelLayout);
        String envName = dialog.getTitle().replace(I18Bundle.getMessage("com.github.aloxc.plugin.restplus.setting.environment.title"),"")
                .replace("(","")
                .replace(")","");
        if (settingType == SettingType.ENVIRONMENT) {
            topPanel.add(nameLabel);
            topPanel.add(nameTextField);
            topPanel.add(contextLabel);
            topPanel.add(contextTextField);
            topPanel.add(httpsLabel);
            topPanel.add(httpsCheckBox);
            topPanel.add(hostLabel);
            topPanel.add(hostTextField);
            topPanel.add(portLabel);
            topPanel.add(portTextField);

            Map<String, EnvironmentConfig> envMap = config.getEnv();

            if (dialog.getTitle().equals(I18Bundle.getMessage("com.github.aloxc.plugin.restplus.setting.environment.new"))) {
                deleteEnvironmentButton.setVisible(false);
                nameTextField.setEnabled(true);
                httpsCheckBox.setSelected(false);
                hostTextField.setText("");
                nameTextField.setText("");
                portTextField.setText(String.valueOf("80"));
            } else {
                EnvironmentConfig environmentConfig = envMap.get(envName);
                nameTextField.setText(environmentConfig.getName());
                https = environmentConfig.isHttps();
                host = environmentConfig.getHost();
                port = environmentConfig.getPort();
                contextTextField.setText(environmentConfig.getContext());
                httpsCheckBox.setSelected(https);
                hostTextField.setText(host);
                portTextField.setText(String.valueOf(port));
                deleteEnvironmentButton.setVisible(true);
                nameTextField.setEnabled(false);
            }
        } else {
            topPanel.add(tipsLabel);
            deleteEnvironmentButton.setVisible(false);
        }

        variatePanel.add(topPanel,
                new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_NORTHWEST, GridConstraints.FILL_BOTH,
                        GridConstraints.SIZEPOLICY_FIXED,
                        GridConstraints.FILL_NONE,
                        topSize, topSize, topSize));
    }

    private void initTable() {
        String[] headers = {I18Bundle.getMessage("com.github.aloxc.plugin.restplus.setting.using"),
                I18Bundle.getMessage("com.github.aloxc.plugin.restplus.setting.type"),
                I18Bundle.getMessage("com.github.aloxc.plugin.restplus.setting.name"),
                I18Bundle.getMessage("com.github.aloxc.plugin.restplus.setting.value"),
                I18Bundle.getMessage("com.github.aloxc.plugin.restplus.setting.delete.checkbox")};
        List<Setting> settingList = null;
        RestConfig config = project.getComponent(RestServicesNavigator.class).getConfig();
        String test = null;
        if (settingType == SettingType.GLOBAL) {
            settingList = config.getGlobalConfig().getSettingList();
            test = config.getGlobalConfig().getTest();
        } else if (settingType == SettingType.ENVIRONMENT) {
            Map<String, EnvironmentConfig> envMap = config.getEnv();
            EnvironmentConfig environmentConfig = envMap.get(envMap.keySet().toArray()[0]);
            settingList = environmentConfig.getSettingList();
            test = environmentConfig.getTest();
        } else if (settingType == SettingType.REQUEST) {
            RequestConfig requestConfig = config.getRequestConfig().get((parentName != null ? parentName + ":" : "") + url);
            if (requestConfig == null) {
                requestConfig = new RequestConfig();
            }
            settingList = requestConfig.getSettingList();
            if (settingList == null) {
                settingList = new ArrayList<>();
            }
            test = requestConfig.getTest();
        }
        testTextArea.setText(test);
        Vector<Vector> cellData = new Vector();
        settingList.stream().sorted(((o1, o2) -> o1.getName().toLowerCase().compareTo(o2.getName().toLowerCase()))).forEach(it -> {
            Vector row = new Vector();
            row.add(it.isSelected());
            row.add(it.getType());
            row.add(it.getName());
            row.add(it.getValue());
            row.add(false);
            cellData.add(row);
        });
        JComboBox comboBox = new JComboBox();
        comboBox.addItem(Consts.VariateType.NONE.getType());
        comboBox.addItem(Consts.VariateType.COOKIE.getType());
        comboBox.addItem(Consts.VariateType.HEADER.getType());
        VariateTableModel model = new VariateTableModel(headers, cellData);
        variateTable.setModel(model);
        variateTable.setRowHeight(30);
        TableColumnModel tcm = variateTable.getColumnModel();
        // selected 复选框
        tcm.getColumn(0).setPreferredWidth(40);
        tcm.getColumn(0).setWidth(40);
        tcm.getColumn(0).setMaxWidth(40);

        // 类型
        tcm.getColumn(1).setCellEditor(new DefaultCellEditor(comboBox));
        tcm.getColumn(1).setCellRenderer(new DefaultTableCellRenderer());
        tcm.getColumn(1).setPreferredWidth(80);
        tcm.getColumn(1).setWidth(80);
        tcm.getColumn(1).setMaxWidth(80);

        // 变量名
        tcm.getColumn(2).setPreferredWidth(250);
        tcm.getColumn(2).setWidth(250);
        tcm.getColumn(2).setMaxWidth(250);

        // 变量值
        tcm.getColumn(3).setPreferredWidth(355);
        tcm.getColumn(3).setWidth(355);
        tcm.getColumn(3).setMaxWidth(355);

        //删除复选框
        tcm.getColumn(4).setPreferredWidth(50);
        tcm.getColumn(4).setWidth(50);
        tcm.getColumn(4).setMaxWidth(50);

        Dimension size460 = new Dimension(-1, 250);
        GridLayoutManager tableLayoutManager = new GridLayoutManager(1, 1);
        tableLayoutManager.setHGap(1);
        tableLayoutManager.setVGap(1);
        tableLayoutManager.setMargin(new Insets(0, 0, 0, 0));
        tablePanel = new JBPanel<>();
        tablePanel.setLayout(tableLayoutManager);

//        ScrollPaneLayout tableScrollLayoutManager = new ScrollPaneLayout();
//        tableScrollLayoutManager.setHorizontalScrollBarPolicy(HORIZONTAL_SCROLLBAR_AS_NEEDED);
//        tableScrollLayoutManager.setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_ALWAYS);
//        tableScrollPanel = new JBScrollPane(VERTICAL_SCROLLBAR_ALWAYS,HORIZONTAL_SCROLLBAR_AS_NEEDED);
//        tableScrollPanel.setLayout(tableScrollLayoutManager);
        tableScrollPanel.setVisible(true);
        tableScrollPanel.setBounds(10,10,10,10);
        tableScrollPanel.setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_AS_NEEDED);

        tableScrollPanel.getViewport().add(variateTable,
                new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_SOUTHEAST, GridConstraints.FILL_BOTH,
                        GridConstraints.FILL_BOTH,
                        GridConstraints.FILL_NONE,
                        size460, size460, size460));
        tablePanel.add(tableScrollPanel,
                new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_SOUTHEAST, GridConstraints.FILL_BOTH,
                        GridConstraints.FILL_BOTH,
                        GridConstraints.FILL_NONE,
                        size460, size460, size460));

        variatePanel.add(tablePanel,
                new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_SOUTHEAST, GridConstraints.FILL_BOTH,
                        GridConstraints.FILL_BOTH,
                        GridConstraints.FILL_NONE,
                        size460, size460, size460));

    }

    private void initTestText() {
        Dimension testLabelDimension = new Dimension(-1, 30);
        variatePanel.add(testLabel,
                new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_NORTHWEST, GridConstraints.FILL_NONE,
                        GridConstraints.SIZEPOLICY_FIXED,
                        GridConstraints.FILL_NONE,
                        testLabelDimension, testLabelDimension, testLabelDimension));
    }

    private void initTest() {
        Dimension textPanelDimension = new Dimension(-1, 230);

        textScrollPanel = new JBScrollPane(testTextArea, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
        textScrollPanel.setPreferredSize(textPanelDimension);
        textScrollPanel.setMaximumSize(textPanelDimension);
        textScrollPanel.setMinimumSize(textPanelDimension);
        variatePanel.add(textScrollPanel,
                new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_NORTHWEST, GridConstraints.FILL_BOTH,
                        GridConstraints.FILL_HORIZONTAL,
                        GridConstraints.FILL_BOTH,
                        textPanelDimension, textPanelDimension, textPanelDimension));

    }

    private void initButton() {
        FlowLayout bottomLayout = new FlowLayout();
        bottomLayout.setHgap(1);
        bottomLayout.setVgap(1);
        bottomLayout.setAlignment(FlowLayout.LEFT);
        buttonPanel = new JBPanel<>();
        buttonPanel.setLayout(bottomLayout);

        int buttonHeight = 26;
        Dimension deleteDimension = new Dimension(200, buttonHeight);
        Dimension otherButtonDimension = new Dimension(100, buttonHeight);
        Dimension panelDimension = new Dimension(-1, 60);
        deleteEnvironmentButton.setPreferredSize(deleteDimension);
        variateCancelButton.setPreferredSize(otherButtonDimension);
        variateDeleteButton.setPreferredSize(otherButtonDimension);
        variateAddButton.setPreferredSize(otherButtonDimension);
        variateSaveButton.setPreferredSize(otherButtonDimension);
        buttonPanel.add(variateCancelButton);
        buttonPanel.add(variateDeleteButton);
        buttonPanel.add(variateAddButton);
        buttonPanel.add(variateSaveButton);
        buttonPanel.add(deleteEnvironmentButton);
        variatePanel.add(buttonPanel,
                new GridConstraints(4, 0, 1, 1, GridConstraints.ANCHOR_NORTHWEST, GridConstraints.FILL_BOTH,
                        GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                        GridConstraints.FILL_NONE | GridConstraints.FILL_NONE,
                        panelDimension, panelDimension, panelDimension));

    }

    public Project getProject() {
        return project;
    }

    public JTextField getNameTextField() {
        return nameTextField;
    }

    public SettingType getSettingType() {
        return settingType;
    }

    private void initAction() {
        this.variateCancelButton.addActionListener(e -> {
            dialog.setVisible(false);
        });
        this.variateAddButton.addActionListener(new VariateAddListener(this));
        //删除该环境
        deleteEnvironmentButton.addActionListener(new DeleteEnvironmentListener(this));

        this.variateDeleteButton.addActionListener(new VariateDeleteListener(this));

        this.variateSaveButton.addActionListener(new VariateSaveListener(this));
    }

    public void addOldEnvironmentListener(String environmentName) {
        Map<String, EnvironmentConfig> envMap = project.getComponent(RestServicesNavigator.class).getConfig().getEnv();
        EnvironmentConfig envConfig = envMap.get(environmentName);
        httpsCheckBox.setSelected(envConfig.isHttps());
        hostTextField.setText(envConfig.getHost());
        portTextField.setText(String.valueOf(envConfig.getPort()));
        nameTextField.setText(environmentName);
        contextTextField.setText(envConfig.getContext());
        settingType = SettingType.ENVIRONMENT;
        dialog.setTitle(I18Bundle.getMessage("com.github.aloxc.plugin.restplus.setting.environment.title") + "(" + environmentName + ")");
        nameLabel.setVisible(true);
        nameTextField.setEnabled(false);
        testTextArea.setText(envConfig.getTest());
        testTextArea.setToolTipText(I18Bundle.getMessage("com.github.aloxc.plugin.restplus.textpane.tooltips.text"));
        VariateTableModel model = (VariateTableModel) getVariateTable().getModel();
        model.removeAll();
        Vector<Vector> cellData = new Vector();
        envConfig.getSettingList().stream().sorted((o1, o2) -> o1.getName().toLowerCase().compareTo(o2.getName().toLowerCase())).forEach(it -> {
            Vector row = new Vector();
            row.add(it.isSelected());
            row.add(it.getType());
            row.add(it.getName());
            row.add(it.getValue());
            row.add(false);
            cellData.add(row);
        });
        model.addRows(cellData);

    }

    @Override
    public void setDialog(Dialog dialog) {
        this.dialog = dialog;
    }

    @Override
    public void setProject(Project project) {
        this.project = project;
    }
}
